#ifndef INPUTMANAGER
#define INPUTMANAGER

#include "GE_Base.h"

///Keyboard codes returned for special keys. Taken from GLFW headers.
namespace Syp
{
#define SYP_KEY_UNKNOWN      -1
#define SYP_KEY_SPACE        32
#define SYP_KEY_SPECIAL      256
#define SYP_KEY_ESC          (SYP_KEY_SPECIAL+1)
#define SYP_KEY_F1           (SYP_KEY_SPECIAL+2)
#define SYP_KEY_F2           (SYP_KEY_SPECIAL+3)
#define SYP_KEY_F3           (SYP_KEY_SPECIAL+4)
#define SYP_KEY_F4           (SYP_KEY_SPECIAL+5)
#define SYP_KEY_F5           (SYP_KEY_SPECIAL+6)
#define SYP_KEY_F6           (SYP_KEY_SPECIAL+7)
#define SYP_KEY_F7           (SYP_KEY_SPECIAL+8)
#define SYP_KEY_F8           (SYP_KEY_SPECIAL+9)
#define SYP_KEY_F9           (SYP_KEY_SPECIAL+10)
#define SYP_KEY_F10          (SYP_KEY_SPECIAL+11)
#define SYP_KEY_F11          (SYP_KEY_SPECIAL+12)
#define SYP_KEY_F12          (SYP_KEY_SPECIAL+13)
#define SYP_KEY_F13          (SYP_KEY_SPECIAL+14)
#define SYP_KEY_F14          (SYP_KEY_SPECIAL+15)
#define SYP_KEY_F15          (SYP_KEY_SPECIAL+16)
#define SYP_KEY_F16          (SYP_KEY_SPECIAL+17)
#define SYP_KEY_F17          (SYP_KEY_SPECIAL+18)
#define SYP_KEY_F18          (SYP_KEY_SPECIAL+19)
#define SYP_KEY_F19          (SYP_KEY_SPECIAL+20)
#define SYP_KEY_F20          (SYP_KEY_SPECIAL+21)
#define SYP_KEY_F21          (SYP_KEY_SPECIAL+22)
#define SYP_KEY_F22          (SYP_KEY_SPECIAL+23)
#define SYP_KEY_F23          (SYP_KEY_SPECIAL+24)
#define SYP_KEY_F24          (SYP_KEY_SPECIAL+25)
#define SYP_KEY_F25          (SYP_KEY_SPECIAL+26)
#define SYP_KEY_UP           (SYP_KEY_SPECIAL+27)
#define SYP_KEY_DOWN         (SYP_KEY_SPECIAL+28)
#define SYP_KEY_LEFT         (SYP_KEY_SPECIAL+29)
#define SYP_KEY_RIGHT        (SYP_KEY_SPECIAL+30)
#define SYP_KEY_LSHIFT       (SYP_KEY_SPECIAL+31)
#define SYP_KEY_RSHIFT       (SYP_KEY_SPECIAL+32)
#define SYP_KEY_LCTRL        (SYP_KEY_SPECIAL+33)
#define SYP_KEY_RCTRL        (SYP_KEY_SPECIAL+34)
#define SYP_KEY_LALT         (SYP_KEY_SPECIAL+35)
#define SYP_KEY_RALT         (SYP_KEY_SPECIAL+36)
#define SYP_KEY_TAB          (SYP_KEY_SPECIAL+37)
#define SYP_KEY_ENTER        (SYP_KEY_SPECIAL+38)
#define SYP_KEY_BACKSPACE    (SYP_KEY_SPECIAL+39)
#define SYP_KEY_INSERT       (SYP_KEY_SPECIAL+40)
#define SYP_KEY_DEL          (SYP_KEY_SPECIAL+41)
#define SYP_KEY_PAGEUP       (SYP_KEY_SPECIAL+42)
#define SYP_KEY_PAGEDOWN     (SYP_KEY_SPECIAL+43)
#define SYP_KEY_HOME         (SYP_KEY_SPECIAL+44)
#define SYP_KEY_END          (SYP_KEY_SPECIAL+45)
#define SYP_KEY_KP_0         (SYP_KEY_SPECIAL+46)
#define SYP_KEY_KP_1         (SYP_KEY_SPECIAL+47)
#define SYP_KEY_KP_2         (SYP_KEY_SPECIAL+48)
#define SYP_KEY_KP_3         (SYP_KEY_SPECIAL+49)
#define SYP_KEY_KP_4         (SYP_KEY_SPECIAL+50)
#define SYP_KEY_KP_5         (SYP_KEY_SPECIAL+51)
#define SYP_KEY_KP_6         (SYP_KEY_SPECIAL+52)
#define SYP_KEY_KP_7         (SYP_KEY_SPECIAL+53)
#define SYP_KEY_KP_8         (SYP_KEY_SPECIAL+54)
#define SYP_KEY_KP_9         (SYP_KEY_SPECIAL+55)
#define SYP_KEY_KP_DIVIDE    (SYP_KEY_SPECIAL+56)
#define SYP_KEY_KP_MULTIPLY  (SYP_KEY_SPECIAL+57)
#define SYP_KEY_KP_SUBTRACT  (SYP_KEY_SPECIAL+58)
#define SYP_KEY_KP_ADD       (SYP_KEY_SPECIAL+59)
#define SYP_KEY_KP_DECIMAL   (SYP_KEY_SPECIAL+60)
#define SYP_KEY_KP_EQUAL     (SYP_KEY_SPECIAL+61)
#define SYP_KEY_KP_ENTER     (SYP_KEY_SPECIAL+62)

#define SYP_MOUSE_BUTTON_LEFT    0
#define SYP_MOUSE_BUTTON_RIGHT   1
#define SYP_MOUSE_BUTTON_MIDDLE  2

///A KeyEvent is generated when a key is pressed
struct KeyEvent
{
	int key;
	int state;
};

///A structure which holds the current state of the mouse
struct MouseState
{
	MouseState():mouseX(0),mouseY(0),mouseLeft(0),mouseRight(0),mouseMiddle(0){};
	int mouseX;
	int mouseY;
	int lastMouseX;
	int lastMouseY;
	bool mouseLeft;
	bool mouseRight;
	bool mouseMiddle;


};

///InputManager handles all incoming input from peripheral devices.
class SYPAPI InputManager
{
public:
	static void initialise();
    static InputManager& getInputManager();

	static void release();
	KeyEvent getKey();
	///Not to be called by user.
	void getInput();
	///Returns a reference to the MouseState. MouseState contains all information regarding the mouse's current state.
	const MouseState& getMouseStateRef();
	
	///Subscribes a function/member function to recieve mouse updates in the form of a referenced MouseState object. The function/member function must return void and take in a MouseState& argument.Any function/member function subscribed to recieve Mouse Updates will recieve the updates every frame.
	void subscribeToMouseUpdates(const MouseUpdateReciever::slot_type& gb);
private:
	boost::signal<void (MouseState& ms,MouseEvent me)> mouseUpdate;		
	static void recieveMouseClick(int key,int state);
	static void recieveKey(int key, int state);
	std::vector<KeyEvent> keyEvent;
	PInt numOfBufferedKeys;
	MouseState ms;
	static InputManager* im;
	
	
};
}
#endif

